// A listener for the bookmarks
var timerUrlChanger_bookmarkListener = {
	onBeginUpdateBatch: function() {},
	onEndUpdateBatch: function() {},
	onItemAdded: function(aItemId, aFolder, aIndex) {
		var thisUrl = timerUrlChanger.bmsvc.getBookmarkURI(aItemId).spec;
		var thisTitle = timerUrlChanger.bmsvc.getItemTitle(aItemId);
		timerUrlChanger.onBookmark(thisUrl);
	},
	onItemRemoved: function(aItemId, aFolder, aIndex) {},
	onItemChanged: function(aBookmarkId, aProperty, aIsAnnotationProperty, aValue) {},
	onItemVisited: function(aBookmarkId, aVisitID, time) {},
	onItemMoved: function(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex) {}
	//QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsINavBookmarkObserver])
};

// A listener for the location bar
var timerUrlChanger_urlBarListener = {	
	QueryInterface: function(aIID){
		if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
       	    aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
       		aIID.equals(Components.interfaces.nsISupports))
     	return this;
   		throw Components.results.NS_NOINTERFACE;
  	},
  	onLocationChange: function(aProgress, aRequest, aURI){
    	timerUrlChanger.processNewURL(aURI);
  	},
	onStateChange: function() {},
	onProgressChange: function() {},
	onStatusChange: function() {},
	onSecurityChange: function() {},
	onLinkIconAvailable: function() {}
};

// A class for the datas associated with an url
function urlData(url) {
	this.url = url;				// the url of the document
	this.time = 0;				// the time of consultation
	this.bookmarked = false;	// is the url bookmarked ?
	this.bookmarkedNow = false;	// hass the url been bookmarked now ?
	
	this.disp = function(){
		var res = "[URL] "+this.url
			+"\n[Consultation time] "+this.time
			+"\n[Bookmarked] "+(this.bookmarked?"Yes":"No")
			+"\n[Bookmarked now] "+(this.bookmarkedNow?"Yes":"No");
		
		return res;
	};
	
	this.addTime = function(t){
		this.time += t;
		return this.time;
	};
	this.bmNow = function(){
		this.bookmarked = true;
		this.bookmarkedNow = true;
	};
}

// The actual extension
var timerUrlChanger = {
	
	oldURL: null,		// the previous url
	currentURL: null,	// the current url
	urls: new Array(),	// all the urls that are opened in the browser
	time: null,			// the last time of the beginning of a consultation
	// the bookmarks service of Mozilla Firefox
	bmsvc: Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Components.interfaces.nsINavBookmarksService),
	// the i/o service of Mozilla Firefox
	ios: Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService),
	
	/*
	 * function getDocTime()
	 * To know how much time the user has consulted the current document.
	 * @return the consultation time of the document
	 */
	getDocTime: function() {
  		var d = new Date();
    	var t = d.getTime();
    	var res = (timerUrlChanger.time?t-timerUrlChanger.time:-1);
    	timerUrlChanger.time = t;
    	return res;
  	},
  	
  	/*
  	 * function addTimeToUrl(url,t)
  	 * To add an amount of time to an url in the array of all the urls.
  	 * @param url: the url to wich add consultation time
  	 * @param t: the amount of time to add
  	 */
  	addTimeToUrl: function(url,t) {
  		if(url=="about:blank") return;
  		timerUrlChanger.urls[url].addTime(t);
  	},
  	
  	/*
  	 * function dispUrlData(url)
  	 * To display the informations binded to an url in a pretty way.
  	 * @param url: 
  	 * @return the string representation of the informations
  	 */
  	dispUrlData: function(url) {
  		if(url=="about:blank") return;
  		return timerUrlChanger.urls[url].disp();
  	},
  	
  	/*
  	 * function compareUrls(u1,u2)
  	 * To know if the 2 urls refer to the same document.
  	 * Warning: the # form
  	 * @param u1: the first url
  	 * @param u2: the second url
  	 */
  	compareUrls: function(u1,u2) {
  		if(u1=="about:blank" || u1=="about:blank") return;
  		if(u1 == u2) return true;
  		if(u1.lastIndexOf("#") == u2.length && u1.substr(0,u2.length) == u2) return true;
  		if(u2.lastIndexOf("#") == u1.length && u2.substr(0,u1.length) == u1) return true;
  		return false;
  	},
  	
  	/*
  	 * function heckAddUrl(url)
  	 * Check in the array of urls if the url already exist, if not, add it in this array.
  	 * @param url: the url to add if necessary in the array
  	 */
  	checkAddUrl: function(url) {
  		if(url=="about:blank") return;
  		var found = false;
  		for(var url2 in timerUrlChanger.urls){
			if(timerUrlChanger.compareUrls(url2,url)){
				//alert("Match with: "+url2);
				found = true;
				break;
			}
	    }
	    //alert(found);
  		if(!found){
    		// if this url was not active, we had it to the array
    		timerUrlChanger.urls[url] = new urlData(url);
    	}
  	},
  	
  	/*
  	 * function onBookmark(url,title)
  	 * To add or change the title of a bookmarked url
  	 * @param url: the bookmarked url
  	 */
  	onBookmark: function(url) {
  		if(url=="about:blank") return;
  		timerUrlChanger.checkAddUrl(url);
  		timerUrlChanger.urls[url].bmNow();
  	},
  	
  	/*
  	 * function sendAndRemoveData(url)
  	 * When a document is no longer consulted, send datas, then remove it.
  	 * Before sending data, the function check if the url is bookmarked.
  	 * This function also check is the document is not consulted in another tab.
  	 * Note: if the function has been called after removing a tab, the "removed" tab is still active
  	 * that's why 1 tab is allowed to contain the same url. If this function is called after loading
  	 * a new document, no other tab are allowed to contain it.
  	 * @param url: the url of the concerned document
  	 * @param nbOfOtherTab: the number of other tabs that are allowed to have the same url.
  	 */
  	sendAndRemoveData: function(url,nbOfOtherTab) {
  		if(url=="about:blank") return;
	  	var foundTab = 0;
	    // Check each tab for the url
	    var numTabs = gBrowser.browsers.length;
	    for(var index=0; index<numTabs; index++) {
	      var currentBrowser = gBrowser.getBrowserAtIndex(index);
	      //if (url == currentBrowser.currentURI.spec) {
	      if(timerUrlChanger.compareUrls(url,currentBrowser.currentURI.spec)) {
	        // another tab contains the same url
	        foundTab ++;
	      }
	    }
	    //alert(foundTab);
		if(foundTab<=nbOfOtherTab){ // the document is NOT consulted in another tab
			// Check if the url is bookmaked
			var uri = timerUrlChanger.ios.newURI(url, null, null);
			timerUrlChanger.urls[url].bookmarked = timerUrlChanger.bmsvc.isBookmarked(uri);
	  		// Send data
	  		alert("Sending:\n"+timerUrlChanger.dispUrlData(url));
	  		// Delete data
			delete timerUrlChanger.urls[url];
		}else{ // the document is consulted in another tab
			// Do nothing
			alert("Send nothing because document consulted in another tab...");
		}
  	},
	
  	/*
  	 * function init()
  	 * To initialize all listeners for the extension.
  	 */
	init: function() {
    	// Listen for location change
    	gBrowser.addProgressListener(timerUrlChanger_urlBarListener,
       		Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
       		
       	// Listen for tab close or select
       	var container = gBrowser.tabContainer;
		container.addEventListener("TabClose", this.tabRemoved, false);
		
		// Listen for page load
		document.getElementById("appcontent").addEventListener("DOMContentLoaded", this.onPageLoad, true);
		
		// Listen to changes concerning bookmarks
		timerUrlChanger.bmsvc.addObserver(timerUrlChanger_bookmarkListener, false);
  	},
  	
  	/*
  	 * function uninit()
  	 * To remove all the listeners for the extension.
  	 */
	uninit: function() {
		// remove all listeners
		gBrowser.removeProgressListener(timerUrlChanger_urlBarListener);
		var container = gBrowser.tabContainer;
		container.removeEventListener("TabClose", this.tabRemoved, false);
		document.getElementById("appcontent").removeEventListener("DOMContentLoaded", this.onPageLoad, true);
		timerUrlChanger.bmsvc.removeObserver(timerUrlChanger_bookmarkListener, false);
	},

	/*
	 * function processNewUrl(aURI)
	 * Function called whenever the url in the location bar changes.
	 * @param aURI: the new URI
	 */
  	processNewURL: function(aURI) {
  		if(aURI == null // anew tab is opened w/o url
  			//|| aURI.spec != timerUrlChanger.currentURL){
  			|| !timerUrlChanger.compareUrls(aURI.spec,timerUrlChanger.currentURL)){
	    	var docTime = timerUrlChanger.getDocTime();
	    	if(docTime != -1 
	    		&& timerUrlChanger.urls[timerUrlChanger.currentURL]){ // if currentURL's tab removed
	    		timerUrlChanger.addTimeToUrl(timerUrlChanger.currentURL,docTime);
	    	}
	    	timerUrlChanger.oldURL = timerUrlChanger.currentURL;
	    	// if a new tab is opened w/o url, aURI is null but the doc is no longer consulted
	    	timerUrlChanger.currentURL = (aURI?aURI.spec:"about:blank");
	    	
	    	timerUrlChanger.checkAddUrl(timerUrlChanger.currentURL);
  		}
  	},

  	/*
  	 * function tabRemoved(event)
  	 * Function called whenever a tab is removed.
  	 * @param event: the event that triggered the function
  	 */
  	tabRemoved: function(event) {
		var urlRemoved = event.target.linkedBrowser.currentURI.spec;
		var browser = gBrowser.getBrowserAtIndex(gBrowser.mTabContainer.selectedIndex);
		if(urlRemoved == browser.currentURI.spec){
			// The current tab is removed
			var docTime = timerUrlChanger.getDocTime();
			timerUrlChanger.addTimeToUrl(urlRemoved,docTime);
		}
		timerUrlChanger.sendAndRemoveData(urlRemoved,1);
  	},

  	/*
  	 * function onPageLoad(aEvent)
  	 * Function called whenever a page is loaded.
  	 * @param aEvent: the event that triggered the function
  	 */
  	onPageLoad: function(aEvent) {
  		if(aEvent.originalTarget.nodeName == "#document"){
    		var doc = aEvent.originalTarget; // document that triggered "onload" event
    		var browser = gBrowser.getBrowserAtIndex(gBrowser.mTabContainer.selectedIndex);
    		if(timerUrlChanger.currentURL == doc.location.href 
    			&& browser.currentURI.spec != "about:blank"){ // document loaded in the active tab
    			timerUrlChanger.sendAndRemoveData(timerUrlChanger.oldURL,0);
    		}else{
    			// document loaded in a background tab
    			timerUrlChanger.checkAddUrl(doc.location.href);
    		}
  		}    	
  	}
  		
};

window.addEventListener("load", function() {timerUrlChanger.init()}, false);
window.addEventListener("unload", function() {timerUrlChanger.uninit()}, false);

/*********************************************************************************************************************/

var iCopyPrintSaveManager = {
	shortCutKeyPressed : function(event) {
		if(event.ctrlKey && (event.keyCode == 67)) {   //ctrl + c pressed
			iCopyPrintSaveManager.iCopy();
		} else if(event.ctrlKey && (event.keyCode == 80)) {   //ctrl + p pressed
			iCopyPrintSaveManager.iPrint();
		} else if(event.ctrlKey && (event.keyCode == 83)) {   //ctrl + s pressed
			iCopyPrintSaveManager.iSave();
		}
	},
	menuItemSelected : function(event) {
		if(event.target.id == "cmd_copy") {   //menuitem 'Copy' clicked
			iCopyPrintSaveManager.iCopy();
		} else if(event.target.id == "cmd_print") {   //menuitem 'Print' clicked
			iCopyPrintSaveManager.iPrint();
		} else if(event.target.id == "Browser:SavePage") {   //menuitem 'Sace page as' clicked
			iCopyPrintSaveManager.iSave();
		}
	},
	iCopy : function() {
		var cpoiedText = gBrowser.contentWindow.getSelection().toString();
		var url = gBrowser.contentWindow.location.href;	
		var logstr = "Text copied: \n[" + cpoiedText + "]. \nFrom address: \n[" + url + "].";
		
		iCopyPrintSaveManager.getConsole().logStringMessage(logstr)
		//alert(logstr);
	},
	iPrint : function() {
		//var pageTitle = gBrowser.contentWindow.title;
		var pageTitle = gBrowser.contentWindow.document.title;
		var url = gBrowser.contentWindow.location.href;
		var logstr = "Page printed: \n[" + pageTitle + "]. \nFrom address: \n[" + url + "].";
		
		iCopyPrintSaveManager.getConsole().logStringMessage(logstr)
		//alert(logstr);
	},
	iSave : function() {
		//var pageTitle = gBrowser.contentWindow.title;
		var pageTitle = gBrowser.contentWindow.document.title;
		var url = gBrowser.contentWindow.location.href;
		var logstr = "Page saved: \n[" + pageTitle + "]. \nFrom address: \n[" + url + "].";
		
		iCopyPrintSaveManager.getConsole().logStringMessage(logstr)
		//alert(logstr);
	},
	getConsole : function() {
		var aConsoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
		aConsoleService.logStringMessage("Logging Message for debug:");
		return aConsoleService;
	}
}

//listener for the corresponding shortcut key press event and the menu item click event
window.addEventListener("keydown", iCopyPrintSaveManager.shortCutKeyPressed, false);
window.addEventListener("command", iCopyPrintSaveManager.menuItemSelected, false);